﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Diagnostics;
using System.Windows.Input;
using System.Dynamic;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Data;
using System.Windows.Controls.Primitives;
using System.ComponentModel.Composition;

namespace ViewMaker.Core.Silverlight
{
    /// <summary>
    /// ViewCommandを処理する既定のヘルパー
    /// </summary>
    [Export(typeof(IViewCommandHelper))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class SlViewCommandHelper : IViewCommandHelper
    {
        private Stack<Cursor> oldCursors;
        private FrameworkElement content;

        /// <summary>
        /// ViewCommandのハンドリングが必要なViewModelを指定する
        /// </summary>
        public IViewCommand ViewModel { get; set; }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public SlViewCommandHelper()
        {
            this.oldCursors = new Stack<Cursor>();
        }

        /// <summary>
        /// 指定したコントロールにヘルパーを割り当てる
        /// </summary>
        /// <param name="control">対象コントロール</param>
        public virtual void Attach(FrameworkElement control)
        {
            this.content = control;
            content.Unloaded += delegate { Detach(); }; //WeakEventManagerで改訂するかは検討する
            this.ViewModel = content.DataContext as IViewCommand;
            if (ViewModel != null)
            {
                ViewModel.ViewCommandNotified += new EventHandler<ViewCommandEventArgs>(viewModel_ViewCommandNotified);
            }
        }

        /// <summary>
        /// 指定したコントロールの割り当てたヘルパーを解除する
        /// </summary>
        public virtual void Detach()
        {
            if (ViewModel != null) ViewModel.ViewCommandNotified -= new EventHandler<ViewCommandEventArgs>(viewModel_ViewCommandNotified);
        }

        void viewModel_ViewCommandNotified(object sender, ViewCommandEventArgs e)
        {
            ExecuteViewCommand(e);

        }

        protected virtual void ExecuteViewCommand(ViewCommandEventArgs e)
        {
            if (content == null) return;
            if (e.Command == ViewCommands.BeginCommand)
            {
                oldCursors.Push(content.Cursor);
                content.Cursor = Cursors.Wait;
            }
            if (e.Command == ViewCommands.EndCommand)
            {
                if (oldCursors.Count > 0) content.Cursor = oldCursors.Pop();
                var ex = e.Parameter as Exception;
                if (ex != null) MessageBox.Show(ex.Message, "エラー", MessageBoxButton.OK);
            }
            if (e.Command == ViewCommands.Validate)
            {
                var info = (ValidateViewCommandInfo)e.Parameter;
                content.UpdateBindingSource(info.AreaName);
                info.IsValid = !content.HasErrorChildren(info.AreaName);
            }

            if (e.Command == ViewCommands.ShowMessage)
            {
                var info = (ShowMessageViewCommandInfo)e.Parameter;
                switch (info.Style)
                {
                    case MessageBoxStyle.Ok:
                        MessageBox.Show(info.Message, info.Title, MessageBoxButton.OK);
                        info.Result = true;
                        return;
                    case MessageBoxStyle.OkCancel:
                        info.Result = MessageBox.Show(info.Message, info.Title, MessageBoxButton.OKCancel) == MessageBoxResult.OK;
                        return;
                    default:
                        throw new NotImplementedException(info.Style.ToString());

                }
            }

            if (e.Command == ViewCommands.ShowOpenFile)
            {
                var info = (SelectFileViewCommandInfo)e.Parameter;
                var dialog = new OpenFileDialog();
                dialog.Filter = info.Filter;
                if (dialog.ShowDialog() == true)
                {
                    info.FileStream = dialog.File.OpenRead();
                }
                else
                {
                    info.FileStream = null;
                }
                return;
            }

            if (e.Command == ViewCommands.ShowSaveFile)
            {
                var info = (SelectFileViewCommandInfo)e.Parameter;
                var dialog = new SaveFileDialog();
                dialog.Filter = info.Filter;
                if (dialog.ShowDialog() == true)
                {
                    info.FileStream = dialog.OpenFile();
                }
                else
                {
                    info.FileStream = null;
                }
                return;
            }

            if (e.Command == ViewCommands.Close)
            {
                var window = this.content as ChildWindow;
                if (window != null) window.Close();
            }
        }

    }

}
